﻿#ifndef DMKEMOTOR_H
#define DMKEMOTOR_H

#include "../can/candevice.h"
#include "motordriver.h"

class DmkeMotor : public MotorDriver {
public:
    DmkeMotor( int pulse_per_round, double length_per_pulse, int left_direction, int right_direction, long acce, long dece );
//    ~DmkeMotor() override;

public:
    void DataFramesMotorInit( CanDataFrame* frames, uint8& i ) override;  // frames数组大小定义要大于等于50
    void DataFramesMotorSpeed( CanDataFrame* frames, uint8& i, double speedl, double speedr ) override;
    void DataFramesMotorRequest( CanDataFrame* frames, uint8& i ) override;
    QString RecDataParse( CanDataFrame* frames, uint8 cnt ) override;
    DMotorFeedBackPara RetMotorFeedbackParam() override;

    //外部调用
    // void SetLiftDrivePosMode();  //回零模式完全后自动设定位置模式
    // void SetTurnDrivePosMode();
    void DataFramesMotorEnable( CanDataFrame* frames, uint8& i ) override;   //左右伺服电机重新使能
    void DataFramesMotorDisable( CanDataFrame* frames, uint8& i ) override;  //左右伺服电机停止失能
    void DataFramesStopMotor( CanDataFrame* frames, uint8& i ) override;              //全部伺服电机设置停止模式
    bool CanSetSendSpeedParm( double left, double right );
    void DataFramesAccDecUpdate( CanDataFrame* frames, uint8& i, double& acc, double& dec ) override;

    // bool SetLiftDrivePositionModePosValue( int value );  //设定位置
    // bool SetTurnDrivePositionModePosValue( int value );  //设定位置
    // UPDATE 2022.07.11获取驱动的错误信息
    void DataFramesGetDriveErrInfo( CanDataFrame* frames, uint8& i ) override;  //获取驱动的错误信息

    void ResetWatchDog( CanDataFrame* frames, uint8& i ) override;
    void AlarmClean( CanDataFrame* frames, uint8& i ) override;  //报警清除


private:
    enum DO_INDEX {
        DO_READ_SPEED       = 0x6069,  //获取伺服速度，INTEGER32 Pulses/s，子索引00
        DO_READ_POS         = 0x6064,  //获取伺服位置，INTEGER32 Pulses，子索引00
        DO_READ_ERR         = 0x2183,  //获取故障信息，子索引00
        DO_PULSES_PER_ROUND = 0x2A90,  //每转所需脉冲数 10000  pulses/rev 重启后生效
                                       //第二编码器分辨率 10000 pulses/mm 立即生效
    };

    // uint8      left_drive_id                            = 0x01;                                                // 左轮伺服id
    // uint8      right_drive_id                           = 0x02;                                                // 右轮伺服id
    // uint8      turn_drive_id                            = 0x03;                                                // 旋转伺服id
    // uint8      lift_drive_id                            = 0x04;                                                // 举升伺服id
    // uint8      can_operation_enable                     = 0x01;                                                // 伺服can操作模式使能
    // uint8      can_operation_disable                    = 0x02;                                                // 伺服can操作模式失能
    uint8 home_mode[ 8 ]                           = { 0x2F, 0x60, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00 };  // 设置伺服回零模式
    uint8 position_mode[ 8 ]                       = { 0x2F, 0x60, 0x60, 0x00, 0x01, 0x00, 0x00, 0x00 };  // 设置伺服位置模式
    uint8 speed_mode[ 8 ]                          = { 0x2F, 0x60, 0x60, 0x00, 0x03, 0x00, 0x00, 0x00 };  // 设置伺服速度模式
    uint8 enable_mode_0F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x0F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能0F
    uint8 enable_mode_1F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x1F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能1F
    uint8 enable_mode_2F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x2F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能2F
    uint8 enable_mode_3F[ 8 ]                      = { 0x2B, 0x40, 0x60, 0x00, 0x3F, 0x00, 0x00, 0x00 };  // 设置伺服软件使能3F
    uint8 disable_mode_00[ 8 ]                     = { 0x2B, 0x40, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 设置伺服软件失能00
    uint8 disable_mode_06[ 8 ]                     = { 0x2B, 0x40, 0x60, 0x00, 0x06, 0x00, 0x00, 0x00 };  // 设置伺服软件失能06
    uint8 set_zero_pos[ 8 ]                        = { 0x23, 0x40, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 编码器位置清零
    uint8 get_cur_speed[ 8 ]                       = { 0x40, 0x69, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取伺服速度
    uint8 get_cur_speed_2[ 8 ]                     = { 0x40, 0x6C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取伺服速度-步科驱动使用
    uint8 get_cur_pos[ 8 ]                         = { 0x40, 0x64, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取伺服位置
    uint8 get_cur_voltage[ 8 ]                     = { 0x40, 0x01, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取电压值
    uint8 set_speed_value[ 4 ]                     = { 0x23, 0xFF, 0x60, 0x00 };                          // 设定速度模式下速度值
    uint8 set_drive_accec[ 4 ]                     = { 0x23, 0x83, 0x60, 0x00 };                          // 设定加速度
    uint8 set_drive_dece[ 4 ]                      = { 0x23, 0x84, 0x60, 0x00 };                          // 设定减速度
    uint8 set_drive_position_mode_speed_value[ 4 ] = { 0x23, 0x81, 0x60, 0x00 };                          // 设定位置模式下的速度值
    uint8 set_drive_position_mode_pos_value[ 4 ]   = { 0x23, 0x7A, 0x60, 0x00 };                          // 设定位置模式下的位置值
    uint8 get_current[ 8 ]                         = { 0x40, 0x1C, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取电流
    uint8 get_err_info[ 8 ]                        = { 0x40, 0x83, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00 };  // 获取故障信息
    uint8 set_node_proetc_time[ 4 ]                = { 0x2B, 0x0C, 0x10, 0x00 };                          // 100C 是节点保护时间(单位:ms)
    uint8 set_node_proetc_factor[ 4 ]              = { 0x2F, 0x0D, 0x10, 0x00 };                          // 100D 是节点保护因子
    int   left_drive_err_info                      = 0;
    int   right_drive_err_info                     = 0;
    // int        left_direction                           = 0;  // 左轮方向修补  根据电机实际安装决定
    // int        right_direction                          = 0;  // 右轮方向修补
    // int        calc_left_puls = 0, calc_right_puls = 0;
    // double     calc_left_reality_speed = 0, calc_right_reality_speed = 0;
    bool is_lift_pos_mode_done = false;
    bool is_turn_pos_mode_done = false;
    // bool       is_connect            = false;
    long acce, dece;

    int    pulse_per_round;
    double length_per_pulse;

    DMotorFeedBackPara mfb_para;

    // CanDataFrame
    void CanDataFrameOperationalMode( CanDataFrame& frame, uint8 value );                      // 伺服电机设置操作模式
    void CanDataFrameSpeedMode( CanDataFrame& frame, uint8 drive_id );                         // 伺服电机设置速度模式
    void CanDataFrameHomeMode( CanDataFrame& frame, uint8 drive_id );                          // 伺服电机设置回零模式
    void CanDataFramePositionMode( CanDataFrame& frame, uint8 drive_id );                      // 伺服电机设置位置模式
    void CanDataFrameControlByte0F( CanDataFrame& frame, uint8 drive_id );                     // 伺服电机使能控制字0F
    void CanDataFrameControlByte1F( CanDataFrame& frame, uint8 drive_id );                     // 伺服电机使能控制字1F
    void CanDataFrameControlByte2F( CanDataFrame& frame, uint8 drive_id );                     // 伺服电机使能控制字2F
    void CanDataFrameControlByte3F( CanDataFrame& frame, uint8 drive_id );                     // 伺服电机使能控制字3F
    void CanDataFrameControlByte00( CanDataFrame& frame, uint8 drive_id );                     // 伺服电机使能控制字00
    void CanDataFrameControlByte06( CanDataFrame& frame, uint8 drive_id );                     // 伺服电机使能控制字06
    void CanDataFrameAcce( CanDataFrame& frame, uint8 drive_id, long value );                  // 伺服电机设置加速度
    void CanDataFrameDece( CanDataFrame& frame, uint8 drive_id, long value );                  // 伺服电机设置减速度
    void CanDataFrameSetSpeedValue( CanDataFrame& frame, uint8 drive_id, long value );         // 伺服电机设置速度值
    void CanDataFrameGetCurSpeedValue( CanDataFrame& frame, uint8 drive_id );                  // 伺服电机获取速度值
    void CanDataFrameGetCurPoseValue( CanDataFrame& frame, uint8 drive_id );                   // 伺服电机获取当前位置
    void CanDataFrameGetCurVoltage( CanDataFrame& frame, uint8 drive_id );                     // 伺服电机获取母线电压值
    void CanDataFrameSetPosModeSpeedValue( CanDataFrame& frame, uint8 drive_id, long value );  // 伺服电机设置位置模式下的速度值
    void CanDataFrameSetPoModePosValue( CanDataFrame& frame, uint8 drive_id, long value );     // 伺服电机设置位置模式下的位置值
    void CanDataFrameGetErrInfo( CanDataFrame& frame, uint8 drive_id );                        // 伺服电机获取故障代码
    void CanDataFrameNodeProtectTimer( CanDataFrame& frame, uint8 drive_id, long value );      //节点保护时间(单位:ms)
    void CanDataFrameNodeProtectFactor( CanDataFrame& frame, uint8 drive_id, long value );     //节点保护因子
    void CanDataFrameRemote( CanDataFrame& frame, uint8 drive_id );                            // 节点超时保护 远程帧

    QString DataParse( NODE_INDEX index, uint8 ( &array )[ 8 ], SMotorFeedBackPara& para ) override;
    QString MotorErrInfo( NODE_INDEX index, int err_info );  //处理故障信息
};

#endif  // DMKEMOTOR_H
